package basics.collections;

import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * Java 集合框架完整指南
 *
 * 本文件提供了 Java 集合框架的全面详细介绍，包括基本概念、各种实现类、常用操作和最佳实践
 */
public class JavaCollectionsGuide {

    public static void main(String[] args) {
        System.out.println("===== Java 集合框架完整指南 =====");
        System.out.println("请查看源代码中的注释获取详细信息，或运行示例查看结果");

        // 运行示例
        listExamples();
        setExamples();
        mapExamples();
        queueExamples();
        utilityExamples();
        java8Examples();
    }

    /**
     * List 接口示例
     */
    private static void listExamples() {
        System.out.println("\n----- List 接口示例 -----");

        // ArrayList 示例
        List<String> arrayList = new ArrayList<>();
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("C++");

        System.out.println("ArrayList: " + arrayList);
        System.out.println("第一个元素: " + arrayList.get(0));
        System.out.println("大小: " + arrayList.size());

        // 修改元素
        arrayList.set(1, "Python 3");
        System.out.println("修改后: " + arrayList);

        // 插入元素
        arrayList.add(1, "JavaScript");
        System.out.println("插入后: " + arrayList);

        // 删除元素
        arrayList.remove("C++");
        System.out.println("删除后: " + arrayList);

        // LinkedList 示例
        LinkedList<String> linkedList = new LinkedList<>();
        linkedList.add("红色");
        linkedList.add("绿色");
        linkedList.add("蓝色");

        System.out.println("\nLinkedList: " + linkedList);

        // LinkedList 特有操作
        linkedList.addFirst("黑色");
        linkedList.addLast("白色");
        System.out.println("添加首尾元素后: " + linkedList);

        System.out.println("第一个元素: " + linkedList.getFirst());
        System.out.println("最后一个元素: " + linkedList.getLast());

        linkedList.removeFirst();
        linkedList.removeLast();
        System.out.println("删除首尾元素后: " + linkedList);
    }

    /**
     * Set 接口示例
     */
    private static void setExamples() {
        System.out.println("\n----- Set 接口示例 -----");

        // HashSet 示例
        Set<String> hashSet = new HashSet<>();
        hashSet.add("Java");
        hashSet.add("Python");
        hashSet.add("C++");
        hashSet.add("Java"); // 重复元素不会被添加

        System.out.println("HashSet: " + hashSet);
        System.out.println("大小: " + hashSet.size());
        System.out.println("包含Java? " + hashSet.contains("Java"));

        // LinkedHashSet 示例
        Set<String> linkedHashSet = new LinkedHashSet<>();
        linkedHashSet.add("Java");
        linkedHashSet.add("Python");
        linkedHashSet.add("C++");

        System.out.println("\nLinkedHashSet (保持插入顺序): " + linkedHashSet);

        // TreeSet 示例
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("Banana");
        treeSet.add("Apple");
        treeSet.add("Orange");
        treeSet.add("Grape");

        System.out.println("\nTreeSet (自然排序): " + treeSet);
        System.out.println("第一个元素: " + treeSet.first());
        System.out.println("最后一个元素: " + treeSet.last());
        System.out.println("小于Orange的最大元素: " + treeSet.lower("Orange"));
        System.out.println("大于Orange的最小元素: " + treeSet.higher("Orange"));
    }

    /**
     * Map 接口示例
     */
    private static void mapExamples() {
        System.out.println("\n----- Map 接口示例 -----");

        // HashMap 示例
        Map<String, Integer> hashMap = new HashMap<>();
        hashMap.put("Java", 1995);
        hashMap.put("Python", 1991);
        hashMap.put("C++", 1983);

        System.out.println("HashMap: " + hashMap);
        System.out.println("Java发布年份: " + hashMap.get("Java"));
        System.out.println("包含Python键? " + hashMap.containsKey("Python"));
        System.out.println("包含1995值? " + hashMap.containsValue(1995));

        // 遍历Map
        System.out.println("\n遍历HashMap:");
        for (Map.Entry<String, Integer> entry : hashMap.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }

        // LinkedHashMap 示例
        Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
        linkedHashMap.put("Java", 1995);
        linkedHashMap.put("Python", 1991);
        linkedHashMap.put("C++", 1983);

        System.out.println("\nLinkedHashMap (保持插入顺序): " + linkedHashMap);

        // TreeMap 示例
        TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("Java", 1995);
        treeMap.put("Python", 1991);
        treeMap.put("C++", 1983);

        System.out.println("\nTreeMap (按键排序): " + treeMap);
        System.out.println("第一个键: " + treeMap.firstKey());
        System.out.println("最后一个键: " + treeMap.lastKey());
    }

    /**
     * Queue 接口示例
     */
    private static void queueExamples() {
        System.out.println("\n----- Queue 接口示例 -----");

        // LinkedList作为Queue
        Queue<String> queue = new LinkedList<>();
        queue.offer("第一个");
        queue.offer("第二个");
        queue.offer("第三个");

        System.out.println("Queue: " + queue);
        System.out.println("队首元素: " + queue.peek());
        System.out.println("移除队首: " + queue.poll());
        System.out.println("移除后: " + queue);

        // PriorityQueue 示例
        PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
        priorityQueue.offer(5);
        priorityQueue.offer(1);
        priorityQueue.offer(3);
        priorityQueue.offer(2);

        System.out.println("\nPriorityQueue: " + priorityQueue);
        System.out.println("移除元素顺序:");
        while (!priorityQueue.isEmpty()) {
            System.out.print(priorityQueue.poll() + " ");
        }
        System.out.println();

        // Deque 示例
        Deque<String> deque = new ArrayDeque<>();
        deque.addFirst("第一个");
        deque.addLast("最后一个");

        System.out.println("\nDeque: " + deque);
        System.out.println("移除首元素: " + deque.removeFirst());
        System.out.println("移除后: " + deque);
    }

    /**
     * 集合工具类示例
     */
    private static void utilityExamples() {
        System.out.println("\n----- 集合工具类示例 -----");

        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(2);
        numbers.add(8);
        numbers.add(1);

        System.out.println("原始List: " + numbers);

        // 排序
        Collections.sort(numbers);
        System.out.println("排序后: " + numbers);

        // 二分查找
        int index = Collections.binarySearch(numbers, 5);
        System.out.println("5的索引: " + index);

        // 反转
        Collections.reverse(numbers);
        System.out.println("反转后: " + numbers);

        // 打乱
        Collections.shuffle(numbers);
        System.out.println("打乱后: " + numbers);

        // 最大值和最小值
        int max = Collections.max(numbers);
        int min = Collections.min(numbers);
        System.out.println("最大值: " + max + ", 最小值: " + min);

        // 集合与数组转换
        System.out.println("\n集合与数组转换:");

        // 数组转List
        String[] array = {"Java", "Python", "C++"};
        List<String> list = new ArrayList<>(Arrays.asList(array));
        System.out.println("数组转List: " + list);

        // List转数组
        String[] newArray = list.toArray(new String[0]);
        System.out.println("List转数组: " + Arrays.toString(newArray));
    }

    /**
     * Java 8+ 新特性示例
     */
    private static void java8Examples() {
        System.out.println("\n----- Java 8+ 新特性示例 -----");

        List<String> languages = Arrays.asList(
                "Java", "Python", "JavaScript", "C++", "Ruby", "Go"
        );

        System.out.println("原始List: " + languages);

        // Stream API - 过滤
        List<String> filtered = languages.stream()
                .filter(lang -> lang.length() > 4)
                .collect(Collectors.toList());

        System.out.println("长度大于4的语言: " + filtered);

        // Stream API - 映射
        List<Integer> lengths = languages.stream()
                .map(String::length)
                .collect(Collectors.toList());

        System.out.println("各语言的长度: " + lengths);

        // forEach方法
        System.out.println("\n使用forEach方法:");
        languages.forEach(lang -> System.out.print(lang + " "));
        System.out.println();

        // Map的新方法
        Map<String, Integer> yearMap = new HashMap<>();
        yearMap.put("Java", 1995);

        // computeIfAbsent
        yearMap.computeIfAbsent("Python", k -> 1991);

        // getOrDefault
        int cYear = yearMap.getOrDefault("C", 1972);

        System.out.println("\nMap操作结果: " + yearMap);
        System.out.println("C的发布年份(默认值): " + cYear);
    }
}

/**
 * =====================================================
 * Java 集合框架详细知识点
 * =====================================================
 *
 * 1. 集合框架概述
 * =====================================================
 *
 * 1.1 什么是集合框架
 * - 集合框架是一个用于表示和操作集合的统一架构
 * - 包含接口、实现类和算法
 * - 位于java.util包中
 * - 解决了数组的局限性问题（固定大小、同质性等）
 *
 * 1.2 集合框架与数组的对比
 *
 * 数组:
 * - 固定长度，一旦创建不能改变大小
 * - 可以存储基本类型和引用类型
 * - 直接通过索引访问元素，性能好
 * - 内存连续分配，对基本类型友好
 * - 没有内置方法，需要借助Arrays工具类
 *
 * 集合:
 * - 动态大小，可以根据需要增长或缩小
 * - 只能存储对象，不能存储基本类型（需要使用包装类）
 * - 提供了丰富的API和操作方法
 * - 支持泛型，提供类型安全
 * - 有多种实现类，适用于不同场景
 *
 * 1.3 集合框架的层次结构
 * - Collection接口：集合层次的根接口
 *   - List接口：有序集合，允许重复元素
 *   - Set接口：不允许重复元素的集合
 *   - Queue接口：表示队列，通常以FIFO方式操作元素
 * - Map接口：键值对映射，不继承自Collection
 *
 * 2. List接口及实现类
 * =====================================================
 *
 * 2.1 List接口特点
 * - 有序集合（插入顺序）
 * - 允许重复元素
 * - 允许null元素
 * - 可以通过索引访问元素
 *
 * 2.2 ArrayList
 * - 基于动态数组实现
 * - 随机访问效率高，时间复杂度O(1)
 * - 插入和删除效率低，可能需要移动元素
 * - 线程不安全
 * - 适用于：频繁随机访问，较少插入删除的场景
 *
 * 常用方法:
 * - add(E e): 在末尾添加元素
 * - add(int index, E element): 在指定位置插入元素
 * - get(int index): 获取指定位置的元素
 * - set(int index, E element): 修改指定位置的元素
 * - remove(int index): 删除指定位置的元素
 * - remove(Object o): 删除指定元素
 * - size(): 获取列表大小
 * - isEmpty(): 检查列表是否为空
 * - contains(Object o): 检查是否包含指定元素
 * - indexOf(Object o): 查找元素首次出现的位置
 * - lastIndexOf(Object o): 查找元素最后出现的位置
 * - clear(): 清空列表
 * - toArray(): 转换为数组
 *
 * 示例:
 * List<String> arrayList = new ArrayList<>();
 * arrayList.add("Java");
 * arrayList.add("Python");
 * arrayList.get(0); // 获取第一个元素
 * arrayList.remove(1); // 删除第二个元素
 *
 * 2.3 LinkedList
 * - 基于双向链表实现
 * - 随机访问效率低，时间复杂度O(n)
 * - 插入和删除效率高，时间复杂度O(1)
 * - 线程不安全
 * - 实现了Deque接口，可以用作队列或栈
 * - 适用于：频繁插入删除，较少随机访问的场景
 *
 * 特有方法:
 * - addFirst(E e): 在头部添加元素
 * - addLast(E e): 在尾部添加元素
 * - getFirst(): 获取第一个元素
 * - getLast(): 获取最后一个元素
 * - removeFirst(): 移除并返回第一个元素
 * - removeLast(): 移除并返回最后一个元素
 * - peek(): 获取但不移除第一个元素
 * - poll(): 移除并返回第一个元素
 * - offer(E e): 在尾部添加元素
 *
 * 示例:
 * LinkedList<String> linkedList = new LinkedList<>();
 * linkedList.add("Java");
 * linkedList.addFirst("Python"); // 在头部添加元素
 * linkedList.addLast("C++"); // 在尾部添加元素
 *
 * 2.4 Vector
 * - 类似ArrayList，但线程安全
 * - 性能较ArrayList差
 * - 已被Collections.synchronizedList()替代
 * - 不推荐使用
 *
 * 2.5 Stack
 * - 继承自Vector
 * - 实现了LIFO（后进先出）栈
 * - 已被Deque接口的实现类替代
 * - 不推荐使用
 *
 * 3. Set接口及实现类
 * =====================================================
 *
 * 3.1 Set接口特点
 * - 不允许重复元素
 * - 最多包含一个null元素
 * - 没有定义顺序
 *
 * 常用方法:
 * - add(E e): 添加元素
 * - remove(Object o): 删除元素
 * - contains(Object o): 检查是否包含元素
 * - size(): 获取集合大小
 * - isEmpty(): 检查集合是否为空
 * - clear(): 清空集合
 *
 * 3.2 HashSet
 * - 基于HashMap实现
 * - 不保证元素顺序
 * - 允许null元素
 * - 查找、添加和删除的时间复杂度为O(1)
 * - 线程不安全
 * - 适用于：需要快速查找、不关心顺序的场景
 *
 * 示例:
 * Set<String> hashSet = new HashSet<>();
 * hashSet.add("Java");
 * hashSet.add("Python");
 * hashSet.add("Java"); // 不会被添加，因为已存在
 *
 * 3.3 LinkedHashSet
 * - 继承自HashSet
 * - 维护元素的插入顺序
 * - 性能略低于HashSet
 * - 适用于：需要保持插入顺序的场景
 *
 * 示例:
 * Set<String> linkedHashSet = new LinkedHashSet<>();
 * linkedHashSet.add("Java");
 * linkedHashSet.add("Python");
 * // 遍历时会按照插入顺序返回元素
 *
 * 3.4 TreeSet
 * - 基于红黑树（TreeMap）实现
 * - 元素按照自然顺序或指定的Comparator排序
 * - 不允许null元素
 * - 查找、添加和删除的时间复杂度为O(log n)
 * - 适用于：需要排序的场景
 *
 * 特有方法:
 * - first(): 返回第一个元素
 * - last(): 返回最后一个元素
 * - lower(E e): 返回小于给定元素的最大元素
 * - higher(E e): 返回大于给定元素的最小元素
 * - floor(E e): 返回小于或等于给定元素的最大元素
 * - ceiling(E e): 返回大于或等于给定元素的最小元素
 * - subSet(E fromElement, E toElement): 返回指定范围内的元素视图
 * - headSet(E toElement): 返回小于指定元素的所有元素视图
 * - tailSet(E fromElement): 返回大于或等于指定元素的所有元素视图
 *
 * 示例:
 * TreeSet<String> treeSet = new TreeSet<>();
 * treeSet.add("Java");
 * treeSet.add("Python");
 * treeSet.add("C++");
 * // 遍历时会按照字母顺序返回元素
 *
 * 4. Map接口及实现类
 * =====================================================
 *
 * 4.1 Map接口特点
 * - 键值对映射
 * - 键不能重复
 * - 每个键最多映射到一个值
 *
 * 常用方法:
 * - put(K key, V value): 添加键值对
 * - get(Object key): 获取指定键的值
 * - remove(Object key): 删除指定键的映射
 * - containsKey(Object key): 检查是否包含指定键
 * - containsValue(Object value): 检查是否包含指定值
 * - size(): 获取映射数量
 * - isEmpty(): 检查映射是否为空
 * - clear(): 清空映射
 * - keySet(): 返回所有键的Set视图
 * - values(): 返回所有值的Collection视图
 * - entrySet(): 返回所有键值对的Set视图
 *
 * 4.2 HashMap
 * - 基于哈希表实现
 * - 不保证映射的顺序
 * - 允许null键和null值
 * - 查找、添加和删除的时间复杂度为O(1)
 * - 线程不安全
 * - 适用于：需要快速查找、不关心顺序的场景
 *
 * 示例:
 * Map<String, Integer> hashMap = new HashMap<>();
 * hashMap.put("Java", 1995);
 * hashMap.put("Python", 1991);
 * hashMap.get("Java"); // 返回1995
 *
 * 4.3 LinkedHashMap
 * - 继承自HashMap
 * - 维护键值对的插入顺序或访问顺序
 * - 性能略低于HashMap
 * - 适用于：需要保持插入顺序的场景
 *
 * 示例:
 * Map<String, Integer> linkedHashMap = new LinkedHashMap<>();
 * linkedHashMap.put("Java", 1995);
 * linkedHashMap.put("Python", 1991);
 * // 遍历时会按照插入顺序返回键值对
 *
 * 4.4 TreeMap
 * - 基于红黑树实现
 * - 键按照自然顺序或指定的Comparator排序
 * - 不允许null键
 * - 查找、添加和删除的时间复杂度为O(log n)
 * - 适用于：需要按键排序的场景
 *
 * 特有方法:
 * - firstKey(): 返回第一个键
 * - lastKey(): 返回最后一个键
 * - lowerKey(K key): 返回小于给定键的最大键
 * - higherKey(K key): 返回大于给定键的最小键
 * - floorKey(K key): 返回小于或等于给定键的最大键
 * - ceilingKey(K key): 返回大于或等于给定键的最小键
 * - subMap(K fromKey, K toKey): 返回指定范围内的映射视图
 *
 * 示例:
 * TreeMap<String, Integer> treeMap = new TreeMap<>();
 * treeMap.put("Java", 1995);
 * treeMap.put("Python", 1991);
 * treeMap.put("C++", 1983);
 * // 遍历时会按照键的字母顺序返回键值对
 *
 * 4.5 Hashtable
 * - 类似HashMap，但线程安全
 * - 不允许null键和null值
 * - 性能较HashMap差
 * - 已被ConcurrentHashMap替代
 * - 不推荐使用
 *
 * 5. Queue接口及实现类
 * =====================================================
 *
 * 5.1 Queue接口特点
 * - 通常以FIFO（先进先出）方式操作元素
 * - 提供了额外的插入、提取和检查操作
 *
 * 常用方法:
 * - offer(E e): 添加元素，如果队列已满返回false
 * - add(E e): 添加元素，如果队列已满抛出异常
 * - poll(): 移除并返回队首元素，如果队列为空返回null
 * - remove(): 移除并返回队首元素，如果队列为空抛出异常
 * - peek(): 返回队首元素但不移除，如果队列为空返回null
 * - element(): 返回队首元素但不移除，如果队列为空抛出异常
 *
 * 5.2 LinkedList
 * - 实现了Deque接口，可用作Queue
 * - 适用于：一般的队列操作
 *
 * 示例:
 * Queue<String> queue = new LinkedList<>();
 * queue.offer("Java"); // 添加元素
 * queue.offer("Python");
 * queue.poll(); // 移除并返回队首元素
 *
 * 5.3 PriorityQueue
 * - 基于优先级堆实现
 * - 元素按照自然顺序或指定的Comparator排序
 * - 不允许null元素
 * - 适用于：需要按优先级处理元素的场景
 *
 * 示例:
 * PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
 * priorityQueue.offer(3);
 * priorityQueue.offer(1);
 * priorityQueue.offer(2);
 * priorityQueue.poll(); // 返回1，最小的元素
 *
 * 5.4 Deque接口及实现类
 * - 双端队列，支持在两端插入和移除元素
 * - 可以用作栈或队列
 */